/* verilator lint_off UNUSEDSIGNAL */

`include "DEFWIDTH.v"

module ID_STAGE(
    input clk,
    input reset,
    //allowin
    output id_allowin,
    input exe_allowin,
    //from if
    input if_to_id_valid,
    input [`IF_TO_ID_BUS_WD -1:0] if_to_id_bus,
    //to exe
    output id_to_exe_valid,
    output [`ID_TO_EXE_BUS_WD -1:0] id_to_exe_bus,
	//from exe
	input [`EXE_TO_ID_BRBUS_WD -1:0] exe_to_id_brbus,
    //to if
    output [`ID_TO_IF_BRBUS_WD -1:0] id_to_if_brbus,
    //from wb
    input [`WB_TO_ID_RFBUS_WD -1:0] wb_to_id_rfbus,
	input [`WB_TO_ID_CFBUS_WD -1:0] wb_to_id_cfbus,
	
    //bypass
    input [`MEM_TO_ID_BYPASS_WD -1:0] exe_to_id_bypass,
    input [4:0] exe_to_id_rdbypass,
    input       exe_to_id_rfwenbypass,
    input [`MEM_TO_ID_BYPASS_WD -1:0] mem_to_id_bypass,
    input [4:0] mem_to_id_rdbypass,
    input       mem_to_id_rfwenbypass,
    input [`WB_TO_ID_BYPASS_WD  -1:0] wb_to_id_bypass,
    input [4:0] wb_to_id_rdbypass,
    input       wb_to_id_rfwenbypass,

	input [`EXE_TO_ID_CFBYPASS_WD -1:0] exe_to_id_cfbypass,
	input [11:0] exe_to_id_csrbypass,
	input       exe_to_id_cfwenbypass,
	input [`MEM_TO_ID_CFBYPASS_WD -1:0] mem_to_id_cfbypass,
	input [11:0] mem_to_id_csrbypass,
	input       mem_to_id_cfwenbypass,
	input [`WB_TO_ID_CFBYPASS_WD -1:0] wb_to_id_cfbypass,
	input [11:0] wb_to_id_csrbypass,
	input       wb_to_id_cfwenbypass,

	input		exe_to_id_loadbypass,
    output      id_to_if_brjmpbypass,
	input		exe_to_id_brjmpbypass
);

//通路
wire [31:0] id_pc,id_inst,id_dnpc;
reg id_valid;
wire id_ready_go,id_flush;
reg  [`IF_TO_ID_BUS_WD -1:0] if_to_id_bus_r;//接受if到id的bus的内容
wire [31:0] src1,src2;


//ID阶段1,处理输入(dst_sel[2]是dst_store)
assign id_ready_go = ~exe_to_id_loadbypass; 
assign id_flush = exe_to_id_brjmpbypass; 
assign id_allowin = !id_valid || (id_ready_go && exe_allowin);//可以接受新的输入数据 = 无数据时（待初始化） || 有数据但流水线不阻塞时（数据可以流向下一级以腾出空位）
wire [4:0] op;
wire [4:0] rs1,rs2,rd;
wire [2:0] func3;
wire func7;
wire op_prefix;//TIPS:识别码的第一位，用于区别nop指令（空指令，全为0）和特殊指令（如lb，可识别部分为0）
always @(posedge clk) begin
    if(reset) begin
        id_valid <= 1'b0;
    end else if(id_allowin) begin
        id_valid <= if_to_id_valid;//如果if不往id传值，则也为无效
    end

    if(if_to_id_valid && id_allowin) begin
        if_to_id_bus_r <= if_to_id_bus;//接受if传来的数据
    end 

end
assign {id_pc, id_dnpc} = if_to_id_bus_r[63:0];
assign id_inst = id_flush ? 32'b0 : if_to_id_bus_r[95:64] ;
assign op  = id_inst[6:2];
assign rs1 = id_inst[19:15];
assign rs2 = id_inst[24:20];
assign rd  = id_inst[11:7];
assign func3  = id_inst[14:12];
assign func7  = id_inst[30];
assign op_prefix = id_inst[0];

assign {
    rf_wen,
    rf_waddr,
    rf_wdata
} = wb_to_id_rfbus;//rf写回输入

assign {
    cf_wen,
    cf_waddr,
    cf_wdata
} = wb_to_id_cfbus;//cf写回输入




//ID阶段2,指令识别
wire [ 4:0] imm_sel;
wire		src_csr_sel;
wire [ 1:0] src1_sel;
wire [ 2:0] src2_sel;
wire [ 3:0] dst_sel;
wire [10:0] alu_op;
wire [ 3:0] ls_op;
wire        id_branch_beq_bne,branch_rs1_eq_rs2,id_branch_bge,id_branch_blt;
wire        id_jal,id_jalr;
wire        id_ebreak,id_ecall;

assign branch_rs1_eq_rs2 = rdata1 == rdata2;

decoder id_dec(
    .op(op),
    .op3({op,func3}),
    .op37({op,func3,func7}),
    .imm_sel(imm_sel),
	.src_csr_sel(src_csr_sel),
    .src1_sel(src1_sel),
    .src2_sel(src2_sel),
    .dst_sel(dst_sel),
    .alu_op(alu_op),
    //load&store
    .ls_op(ls_op),
    //branch
    .branch_rs1_eq_rs2(branch_rs1_eq_rs2),
    .branch_beq_bne(id_branch_beq_bne),
	.branch_bge(id_branch_bge),
	.branch_blt(id_branch_blt),
    //jump
    .jal(id_jal),
    .jalr(id_jalr),
	//ecall
	.ecall(id_ecall),
    //ebreak
    .op_ebreak(id_inst[20]),
    .ebreak(id_ebreak),
    .op_prefix(op_prefix)
);


//ID阶段3,立即数识别
wire [31:0] imm;
identIMM id_identIMM(
    .instr(id_inst),
    .imm_sel(imm_sel),
    .imm(imm)
);

//ID阶段4,寄存器读写

wire rf_wen;
wire [4:0] rf_raddr1,rf_raddr2,rf_waddr;
wire [31:0] rf_rdata1,rf_rdata2,rf_wdata;

assign rf_raddr1 = rs1;
assign rf_raddr2 = rs2;

RegisterFile id_rf(
    .clk     (clk      ),
    .raddr_a (rf_raddr1),
    .rdata_a (rf_rdata1),
    .raddr_b (rf_raddr2),
    .rdata_b (rf_rdata2),
    .wen     (rf_wen   ),
    .waddr   (rf_waddr ),
    .wdata   (rf_wdata )
);



wire cf_wen;
wire [11:0] cf_raddr,cf_waddr;
wire [31:0] cf_rdata,cf_wdata;
wire [31:0] id_tvec;

assign cf_raddr = imm[11:0];

CsrFile id_cf(
	.clk(clk),
	.reset(reset),
	.ecall(id_ecall),
	.epc(id_pc),
	.cause(32'hb),
	.tvec(id_tvec),
	
	.raddr(cf_raddr),
	.rdata(cf_rdata),
	.wen(cf_wen),
	.waddr(cf_waddr),
	.wdata(cf_wdata)
);

//ID阶段5,处理输出
assign id_to_exe_valid = id_valid && id_ready_go;

wire [31:0] rdata1,rdata2,crdata;
wire exe_rd_eq_rs1,exe_rd_eq_rs2,exe_csr_eq_csr;
wire mem_rd_eq_rs1,mem_rd_eq_rs2,mem_csr_eq_csr;
wire wb_rd_eq_rs1,wb_rd_eq_rs2,wb_csr_eq_csr;

assign exe_rd_eq_rs1 = exe_to_id_rdbypass == rs1 & rs1!=5'b0;
assign exe_rd_eq_rs2 = exe_to_id_rdbypass == rs2 & rs2!=5'b0;
assign exe_csr_eq_csr = exe_to_id_csrbypass == cf_raddr;

assign mem_rd_eq_rs1 = mem_to_id_rdbypass == rs1 & rs1!=5'b0;
assign mem_rd_eq_rs2 = mem_to_id_rdbypass == rs2 & rs2!=5'b0;
assign mem_csr_eq_csr = mem_to_id_csrbypass == cf_raddr;


assign wb_rd_eq_rs1  = wb_to_id_rdbypass  == rs1 & rs1!=5'b0;
assign wb_rd_eq_rs2  = wb_to_id_rdbypass  == rs2 & rs2!=5'b0;
assign wb_csr_eq_csr  = wb_to_id_csrbypass  == cf_raddr;

//旁路优先选择器，以后不要使用rf_rdata，均使用rdata
assign rdata1 = (exe_to_id_rfwenbypass & exe_rd_eq_rs1) ? exe_to_id_bypass :
                (mem_to_id_rfwenbypass & mem_rd_eq_rs1) ? mem_to_id_bypass :
                (wb_to_id_rfwenbypass  & wb_rd_eq_rs1 ) ? wb_to_id_bypass  : rf_rdata1;

assign rdata2 = (exe_to_id_rfwenbypass & exe_rd_eq_rs2) ? exe_to_id_bypass :
                (mem_to_id_rfwenbypass & mem_rd_eq_rs2) ? mem_to_id_bypass :
                (wb_to_id_rfwenbypass  & wb_rd_eq_rs2 ) ? wb_to_id_bypass  : rf_rdata2;

assign crdata = 32'b0;


assign src1 = src1_sel[0] ? rdata1  :
			  src_csr_sel ? crdata  : id_pc;

assign src2 = src2_sel[0] ? imm     :
              src2_sel[1] ? rdata2  : 
			  src_csr_sel ? ~rdata1 : 32'h4;
assign id_to_exe_bus = {
    src1, //32
    src2, //32
    dst_sel, //4
    ls_op, //4
	rdata1,//32，用于csr
    rdata2,//32，用于store
    rd, //5
    alu_op, //11
	imm, //32，用于branch或csr
	id_branch_bge, //1
	id_branch_blt, //1
    id_pc, //32
	id_dnpc, //32
	id_inst, //32
    id_ebreak, //1
	id_ecall, //1
	id_tvec //32
};

wire [31:0] id_jalr_dst;

assign id_to_if_brjmpbypass = exe_to_id_brjmpbypass | ((id_branch_beq_bne | id_jal | id_jalr) & id_valid);
assign id_jalr_dst = rdata1 + imm;//debug:不要使用rf_rdata
assign id_to_if_brbus =	 exe_to_id_brjmpbypass		  ?	exe_to_id_brbus	:
						(id_branch_beq_bne || id_jal) ? id_pc + imm		: {id_jalr_dst[31:1],1'b0};



endmodule
